home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / async / ASync.txt
Encoding:
Text File  |  1992-10-26  |  11.3 KB  |  323 lines

  1.  
  2. (c)  Copyright 1992 Commodore-Amiga, Inc.   All rights reserved. The
  3. information contained herein is subject to change without notice, and
  4. is provided "as is" without warranty of any kind, either expressed or
  5. implied.  The entire risk as to the use of this information is
  6. assumed by the user.
  7.  
  8.  
  9. Fast AmigaDOS I/O
  10.  
  11.  
  12. by Martin Taillefer
  13.  
  14. Reading and writing data is crucial to most applications and is, in
  15. many cases, a major bottleneck.  Using the Amiga's sophisticated file
  16. system architecture can help reduce, and sometimes eliminate, the
  17. time spent waiting for I/O to complete.  This article presents six
  18. small routines that can greatly improve an application's I/O
  19. performance.
  20.  
  21. Typically, an application processes a file in the following manner:
  22.  
  23. Step 1: Open the file.
  24.  
  25. Step 2: Read some data (with the DOS library's Read() function).
  26.  
  27. Step 3: Process that data.
  28.  
  29. Step 4: Repeat steps 2 and 3 until the application is finished
  30.    processing the file.
  31.  
  32. Step 5: Close file.
  33.  
  34. This sequence of steps is effective, but it does have a potential
  35. bottleneck.  Whenever the application reads some data using the DOS
  36. Read() function, the Amiga has to put that task to sleep and ask the
  37. file system to fetch the data.  The file system then starts up the
  38. disk hardware and reads the data.  After the file system finishes
  39. reading the data, the operating system wakes up the application.
  40.  
  41. The problem is step 2.  While the file system is busy reading data
  42. from the disk, the application is idle, waiting for the DOS I/O in
  43. Read() to complete.  A more sophisticated application would initiate
  44. an asynchronous read, allowing the application to continue to do some
  45. other important chore while the file system is busy reading.  If all
  46. goes well, the file system will be finished with the asynchronous
  47. read by the time the application is finished with its chore, so the
  48. application will not have to wait for any DOS I/O to complete before
  49. the application can access data.
  50.  
  51.  
  52. Using the routines presented in this article, an application
  53. processes a file in the following manner:
  54.  
  55. Step 1:  Open the file with OpenAsync().  This function opens the
  56.    file and, if the file is opened for reading, OpenAsync() asks the
  57.    file system to start reading data, asynchronously.
  58.  
  59. Step 2:  Read some data with ReadAsync().  If the asynchronous read
  60.    request that OpenAsync() sent has not completed, ReadAsync() will
  61.    put the application to sleep until that request returns.  Ideally,
  62.    the read will have returned, so the application won't have to wait.
  63.    ReadAsync() will also initiate a new asynchronous read so new file
  64.    data is ready when the application needs it.
  65.  
  66. Step 3:  Process the file data.
  67.  
  68. Step 4:  Repeat steps 2 and 3 until the application processes all its
  69.    file data.
  70.  
  71. Step 5:  Close the file with CloseAsync().
  72.  
  73. Immediately after opening the file, OpenAsync() sends a request to
  74. the file system to get it reading data in the background.  If all
  75. goes well, by the time the application gets around to reading the
  76. first byte of data, the file system has already copied the data into
  77. memory.  That means the application doesn't need to wait and can
  78. immediately start processing the data.  As soon as the application
  79. starts processing data from the file using ReadAsync(), ReadAsync()
  80. sends out a second request to the file system to fill up a second
  81. buffer.  Once the application is done processing the first buffer, it
  82. starts processing the second one.  When this happens, the file system
  83. starts filling up the first buffer again with new data.  This process
  84. continues until the application has read all of its data.  This
  85. technique is known as ``double-buffered asynchronous I/O''.
  86.  
  87. The set of functions presented below offer high-performance I/O using
  88. the technique described above.  The interface is very similar to
  89. standard AmigaDOS files.  These routines enable full asynchronous
  90. read/write of any file.
  91.  
  92. These functions are especially useful on an Amiga with a DMA (Direct
  93. Memory Access) hard drive.  DMA makes it possible to transfer data to
  94. memory at the same time the CPU is busy executing a task's
  95. instructions.  A DMA data transfer is truly parallel, so, under
  96. normal conditions, the CPU is operating at full speed, unaffected by
  97. the DMA transfer.  This parallelism is what makes the set of
  98. accompanying routines so efficient.  They exploit the fact that the
  99. Amiga can transfer an application's data while the application is
  100. busy processing other data.
  101.  
  102. Although these asynchronous routines make disk I/O much faster, they
  103. do have an important limitation.  The routines do not support seeking
  104. into a file.
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111. TABLE OF CONTENTS
  112.  
  113. asyncio/CloseAsync
  114. asyncio/OpenAsync
  115. asyncio/ReadAsync
  116. asyncio/ReadAsyncChar
  117. asyncio/WriteAsync
  118. asyncio/WriteAsyncChar
  119.  
  120.  
  121. asyncio/CloseAsync                                         asyncio/CloseAsync
  122.  
  123.    NAME
  124.         CloseAsync -- close an async io file.
  125.  
  126.    SYNOPSIS
  127.         result = CloseAsync(file);
  128.  
  129.         LONG CloseAsync(struct AsyncFile *);
  130.  
  131.    FUNCTION
  132.         Closes a file, flushing any pending writes.  Once this call has been
  133.         made, the file can no longer be accessed.
  134.  
  135.    INPUTS
  136.         file - the file to close.  May be NULL.
  137.  
  138.    RESULT
  139.         result - < 0 for an error, >= 0 for success.  Indicates whether closing
  140.                  the file worked or not.  If the file was opened in read-mode,
  141.                  then this call will always work.  In case of error,
  142.                  dos.library/IoErr() can give more information.
  143.  
  144.    SEE ALSO
  145.         OpenAsync, dos.library/Close()
  146.  
  147.  
  148. asyncio/OpenAsync                                           asyncio/OpenAsync
  149.  
  150.    NAME
  151.         OpenAsync -- open a file for asynchronous IO.
  152.  
  153.    SYNOPSIS
  154.         file = OpenAsync(fileName, accessMode, bufferSize);
  155.  
  156.         struct AsyncFile OpenAsync(STRPTR, UBYTE, LONG);
  157.  
  158.    FUNCTION
  159.         The named file is opened and an async file handle returned.  If the
  160.         accessMode is MODE_READ, an existing file is opened for reading.
  161.         If the value is MODE_WRITE, a new file is created for writing.  If
  162.         a file of the same name already exists, it is first deleted.  If
  163.         accessMode is MODE_APPEND, an existing file is prepared for writing.
  164.         Data written is added to the end of the file.  If the file does not
  165.         exists, it is created.
  166.  
  167.         'fileName' is a filename and CANNOT be a simple device such as NIL:, a
  168.         window specification such as CON: or RAW:, or "*".
  169.  
  170.         'bufferSize' specifies the size of the IO buffer to use.  There are
  171.         in fact two buffers allocated, each of roughly (bufferSize/2) bytes
  172.         in size.  The actual buffer size use can vary slightly as the size
  173.         is rounded to speed up DMA.
  174.  
  175.         If the file cannot be opened for any reason, the value returned
  176.         will be NULL, and a secondary error code will be available by
  177.         calling the routine dos.library/IoErr().
  178.  
  179.     INPUTS
  180.         name - name of the file to open
  181.         accessMode - one of MODE_READ, MODE_WRITE, or MODE_APPEND
  182.         bufferSize - size of IO buffer to use.  8192 is recommended as it
  183.                      provides very good performance for relatively little
  184.                      memory.
  185.  
  186.     RESULTS
  187.         file - an async file handle or NULL for failure.  You should not access
  188.                the fields in the AsyncFile structure, these are private to the
  189.                async IO routines.  In case of failure, dos.library/IoErr() can
  190.                give more information.
  191.  
  192.     SEE ALSO
  193.         CloseAsync(), dos.library/Open()
  194.  
  195.  
  196. asyncio/ReadAsync                                           asyncio/ReadAsync
  197.  
  198.    NAME
  199.         ReadAsync -- read bytes from an async file.
  200.  
  201.    SYNOPSIS
  202.         actualLength = ReadAsync(file,buffer,numBytes);
  203.  
  204.         LONG ReadAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);
  205.  
  206.    FUNCTION
  207.         Read() reads bytes of information from an opened async file
  208.         into the buffer given.  'numBytes' is the number of bytes to read from
  209.         the file.
  210.  
  211.         The value returned is the length of the information actually read.
  212.         So, when 'actualLength' is greater than zero, the value of
  213.         'actualLength' is the the number of characters read.  Usually
  214.         ReadAsync() will try to fill up your buffer before returning.  A value
  215.         of zero means that end-of-file has been reached.  Errors are indicated
  216.         by a value of -1.
  217.  
  218.     INPUTS
  219.         file - opened file to read, as obtained from OpenAsync()
  220.         buffer - buffer where to put bytes read
  221.         numBytes - number of bytes to read into buffer
  222.  
  223.     RESULT
  224.         actualLength - actual number of bytes read, or -1 if an error.  In
  225.                        case of error, dos.library/IoErr() can give more
  226.                        information.
  227.  
  228.     SEE ALSO
  229.         OpenAsync(), CloseAsync(), WriteAsync(), ReadCharAsync(),
  230.         dos.library/Read()
  231.  
  232.  
  233.  
  234. asyncio/ReadCharAsync                                   asyncio/ReadCharAsync
  235.  
  236.    NAME
  237.         ReadCharAsync -- read a single byte from an async file.
  238.  
  239.    SYNOPSIS
  240.         byte = ReadCharAsync(file);
  241.  
  242.         LONG ReadCharAsync(struct AsyncFile *file);
  243.  
  244.    FUNCTION
  245.         This function reads a single byte from an async file.  The byte is
  246.         returned, or -1 if there was an error reading, or if the end-of-file
  247.         was reached.
  248.  
  249.    INPUTS
  250.         file - opened file to read from, as obtained from OpenAsync()
  251.  
  252.    RESULT
  253.         byte - the byte read, or -1 if no byte was read.  In case of error,
  254.                dos.library/IoErr() can give more information.
  255.  
  256.    SEE ALSO
  257.         OpenAsync(), CloseAsync(), WriteCharAsync(), ReadAsync()
  258.         dos.library/Read()
  259.  
  260.  
  261.  
  262. asyncio/WriteAsync                                         asyncio/WriteAsync
  263.  
  264.    NAME
  265.         WriteAsync -- write data to an async file.
  266.  
  267.    SYNOPSIS
  268.         actualLength = WriteAsync(file,buffer,numBytes);
  269.  
  270.         LONG WriteAsync(struct AsyncFile *file, APTR buffer, LONG numBytes);
  271.  
  272.    FUNCTION
  273.         WriteAsync() writes bytes of data to an opened async file.  'numBytes'
  274.         indicates the number of bytes of data to be transferred.  'buffer'
  275.         points to the data to write.  The value returned is the length of
  276.         information actually written.  So, when 'numBytes' is greater than
  277.         zero, the value of 'numBytes' is the number of characters written.
  278.         Errors are indicated by a value of -1.
  279.  
  280.     INPUTS
  281.         file - an opened file, as obtained from OpenAsync()
  282.         buffer - address of data to write
  283.         numBytes - number of bytes to write to the file
  284.  
  285.     RESULT
  286.         actualLength - number of bytes written, or -1 if error.  In case
  287.                        of error, dos.library/IoErr() can give more
  288.                        information.
  289.  
  290.     SEE ALSO
  291.         OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
  292.         dos.library/Write
  293.  
  294.  
  295.  
  296.  
  297. asyncio/WriteCharAsync                                 asyncio/WriteCharAsync
  298.  
  299.    NAME
  300.         WriteCharAsync -- write a single byte to an async file.
  301.  
  302.    SYNOPSIS
  303.         result = WriteCharAsync(file,byte);
  304.  
  305.         LONG WriteCharAsync(struct AsyncFile *, UBYTE byte);
  306.  
  307.    FUNCTION
  308.         This function write a single byte to an async file.
  309.  
  310.    INPUTS
  311.         file - an opened async file, as obtained from OpenAsync()
  312.         byte - byte of data to add to the file
  313.  
  314.    RESULT
  315.         result - 1 if the byte was written, -1 if there was an error.  In
  316.                  case of error, dos.library/IoErr() can give more information.
  317.  
  318.    SEE ALSO
  319.         OpenAsync(), CloseAsync(), ReadAsync(), WriteCharAsync(),
  320.         dos.library/Write
  321.  
  322.  
  323.